{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Function Calling and API Calls\n",
    "\n",
    "A lot of projects with Langchain are just scripts executed on a local computer. In the \"real world\", production ready\n",
    "services run in some kind of standardized wrapper, like an API inside a Docker container. This is an approach how you might\n",
    "interact with a REST-API with an LLM Chain (which might later also be used inside an API withh a single POST endpoint)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "import os\n",
    "import openai\n",
    "\n",
    "load_dotenv()\n",
    "openai.api_key = os.environ.get(\"OPENAI_API_KEY\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "def get_todos(completed=None):\n",
    "    params = {'completed': completed} if completed is not None else None\n",
    "    response = requests.get('https://fastapilangchain-1-w0858112.deta.app/todos', params=params)\n",
    "    return response.json()\n",
    "\n",
    "def create_todo(todo):\n",
    "    response = requests.post('https://fastapilangchain-1-w0858112.deta.app/todos', json=todo)\n",
    "    return response.json()\n",
    "\n",
    "def update_todo(id, todo):\n",
    "    response = requests.put(f'https://fastapilangchain-1-w0858112.deta.app/todos/{id}', json=todo)\n",
    "    return response.json()\n",
    "\n",
    "def delete_todo(id):\n",
    "    response = requests.delete(f'https://fastapilangchain-1-w0858112.deta.app/todos/{id}')\n",
    "    return response.status_code  \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "api_functions = {\n",
    "    \"get_todos\": get_todos,\n",
    "    \"create_todo\": create_todo,\n",
    "    \"update_todo\": update_todo,\n",
    "    \"delete_todo\": delete_todo\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "functions = [\n",
    "    {\n",
    "        \"name\": \"get_todos\",\n",
    "        \"description\": \"Get a list of todos, optionally filtered by their completion status\",\n",
    "        \"parameters\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"completed\": {\n",
    "                    \"type\": \"boolean\",\n",
    "                    \"description\": \"Whether to only return completed todos\",\n",
    "                },\n",
    "            },\n",
    "            \"required\": [],\n",
    "        },\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"create_todo\",\n",
    "        \"description\": \"Create a new todo\",\n",
    "        \"parameters\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"todo\": {\n",
    "                    \"type\": \"object\",\n",
    "                    \"description\": \"The new todo to be created\",\n",
    "                    \"properties\": {\n",
    "                        \"id\": {\n",
    "                            \"type\": \"integer\",\n",
    "                            \"description\": \"The id of the todo\",\n",
    "                        },\n",
    "                        \"task\": {\n",
    "                            \"type\": \"string\",\n",
    "                            \"description\": \"The task of the todo\",\n",
    "                        },\n",
    "                        \"is_completed\": {\n",
    "                            \"type\": \"boolean\",\n",
    "                            \"description\": \"Whether the task is completed\",\n",
    "                            \"default\": False\n",
    "                        },\n",
    "                    },\n",
    "                    \"required\": [\"task\"],\n",
    "                },\n",
    "            },\n",
    "            \"required\": [\"todo\"],\n",
    "        },\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"update_todo\",\n",
    "        \"description\": \"Update an existing todo\",\n",
    "        \"parameters\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"id\": {\n",
    "                    \"type\": \"integer\",\n",
    "                    \"description\": \"The id of the todo to update\",\n",
    "                },\n",
    "                \"todo\": {\n",
    "                    \"type\": \"object\",\n",
    "                    \"description\": \"The updated todo\",\n",
    "                    \"properties\": {\n",
    "                        \"task\": {\n",
    "                            \"type\": \"string\",\n",
    "                            \"description\": \"The updated task of the todo\",\n",
    "                        },\n",
    "                        \"is_completed\": {\n",
    "                            \"type\": \"boolean\",\n",
    "                            \"description\": \"The updated completion status of the task\",\n",
    "                        },\n",
    "                    },\n",
    "                    \"required\": [\"task\"],\n",
    "                },\n",
    "            },\n",
    "            \"required\": [\"id\", \"todo\"],\n",
    "        },\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"delete_todo\",\n",
    "        \"description\": \"Delete an existing todo\",\n",
    "        \"parameters\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\n",
    "                \"id\": {\n",
    "                    \"type\": \"integer\",\n",
    "                    \"description\": \"The id of the todo to delete\",\n",
    "                },\n",
    "            },\n",
    "            \"required\": [\"id\"],\n",
    "        },\n",
    "    }\n",
    "]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "query=\"I want to walk my dog in the afternoon\"\n",
    "\n",
    "response = openai.ChatCompletion.create(\n",
    "        model=\"gpt-3.5-turbo-0613\",\n",
    "        messages=[{\"role\": \"user\", \"content\": query}],\n",
    "        functions=functions,\n",
    "    )\n",
    "message = response[\"choices\"][0][\"message\"]\n",
    "\n",
    "message"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "if message.get(\"function_call\"):\n",
    "    function_name = message[\"function_call\"][\"name\"]\n",
    "    function_args_json = message[\"function_call\"].get(\"arguments\", {})\n",
    "    function_args = json.loads(function_args_json)\n",
    "\n",
    "    api_function = api_functions.get(function_name)\n",
    "\n",
    "    if api_function:\n",
    "        result = str(api_function(**function_args)) \n",
    "    else:\n",
    "        print(f\"Function {api_function} not found\")\n",
    "\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "second_response = openai.ChatCompletion.create(\n",
    "    model=\"gpt-3.5-turbo-0613\",\n",
    "    messages=[\n",
    "        {\"role\": \"user\", \"content\": query},\n",
    "        message,\n",
    "        {\n",
    "            \"role\": \"function\",\n",
    "            \"name\": function_name,\n",
    "            \"content\": result,\n",
    "        },\n",
    "    ],\n",
    ")\n",
    "\n",
    "second_response"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
